package controller.impl;

import java.util.LinkedList;
import java.util.Queue;

import model.IControllerModel;
import model.impl.IModelListener;
import model.impl.Model;
import network.NetworkFactory;
import network.impl.ClientNetworkListener;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.GameState;
import org.newdawn.slick.state.StateBasedGame;

import view.IView;
import view.ViewFactory;
import view.impl.RenderException;


class GameStateController implements GameState, IModelListener, ClientNetworkListener {
	private static final GameStateController INSTANCE = new GameStateController();
	private IView view;
	private IControllerModel model = Model.getControllerModel();
	private LinkedList<KeyPress> keyPresses;
	private boolean gameRunning;
	private Queue<Object> incomingData;

	
	private GameStateController() {
		try {
			view = ViewFactory.getView();
		} catch (RenderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		keyPresses = new LinkedList<KeyPress>();
		gameRunning = true;
		model.init();
		model.addIModelListener(this);
		NetworkFactory.newNetwork(this, Model.getNetworkModel());
		incomingData = new LinkedList<Object>();
	}
	
	public static GameStateController getInstance() {
		return INSTANCE;
	}
	
	@Override
	public void enter(GameContainer arg0, StateBasedGame arg1)
			throws SlickException {
		
	}

	@Override
	public int getID() {
		return 0;
	}

	@Override
	public void init(GameContainer container, StateBasedGame game)
			throws SlickException {
	}

	@Override
	public void leave(GameContainer container, StateBasedGame game)
			throws SlickException {
		
	}

	@Override
	public void render(GameContainer container, StateBasedGame game, Graphics g)
			throws SlickException {
		try {
			view.render(container, g);
		} catch (RenderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void update(GameContainer container, StateBasedGame game, int delta)
			throws SlickException {
		if (!gameRunning) {
			container.exit();
		}
		if (container.isFullscreen() != model.isFullScreen()) {
			container.setFullscreen(model.isFullScreen());
		}
		if (!incomingData.isEmpty()) {
			Object obj = incomingData.poll();
			model.newData(obj, delta);
		}
		if (!keyPresses.isEmpty()) {
			model.newInput(keyPresses.removeFirst(), delta);
		}
	}

	@Override
	public void mouseClicked(int button, int x, int y, int clickCount) {
		
	}

	@Override
	public void mouseMoved(int oldx, int oldy, int newx, int newy) {
		
	}

	@Override
	public void mousePressed(int button, int x, int y) {
		
	}

	@Override
	public void mouseReleased(int button, int x, int y) {
		
	}

	@Override
	public void mouseWheelMoved(int change) {
		
	}

	@Override
	public void inputEnded() {
		
	}

	@Override
	public boolean isAcceptingInput() {
		return true;
	}

	@Override
	public void setInput(Input input) {
	}

	@Override
	public void keyPressed(int key, char c) {
		keyPresses.addLast(new KeyPress(key, c));
	}

	@Override
	public void keyReleased(int key, char c) {
		
	}

	@Override
	public void controllerButtonPressed(int controller, int button) {
		
	}

	@Override
	public void controllerButtonReleased(int controller, int button) {
		
	}

	@Override
	public void controllerDownPressed(int controller) {
		
	}

	@Override
	public void controllerDownReleased(int controller) {
		
	}

	@Override
	public void controllerLeftPressed(int controller) {
		
	}

	@Override
	public void controllerLeftReleased(int controller) {
		
	}

	@Override
	public void controllerRightPressed(int controller) {
		
	}

	@Override
	public void controllerRightReleased(int controller) {
		
	}

	@Override
	public void controllerUpPressed(int controller) {
		
	}

	@Override
	public void controllerUpReleased(int controller) {
		
	}

	@Override
	public void exit() {
		gameRunning = false;		
	}

	@Override
	public void networkMessageRecieved(Object obj) {
		incomingData.add(obj);
	}

	@Override
	public void connectionFailed() {
		//TODO: Add logic for connection failed.
	}

	@Override
	public void serverAddressNotFound() {
		// TODO Add code for address not found.
	}
}
